import glo
'''
函数只要写了，就不分定义的前后顺序，都能互相调用，这点和c不同，c需要声明才不分前后顺序
'''
m1 = glo.Memory()

def block_find_by_Time():
    minTime = glo.Time[0]
    block_id = 0
    for i in range(glo.bn):
        if glo.Time[i] < minTime:
            minTime = glo.Time[i]
            block_id = i
    return block_id

'''
f = False//默认关闭计数器
'''

def block_update(content, block_id, f = False):
    data = m1.getblock(block_id)
    m1.updateblock(block_id,content)
    if f == True:
        glo.Time_count = glo.Time_count+1
        glo.Time[glo.Time_pos] =glo.Time_count
        glo.Time_pos = glo.Time_pos+1
        glo.Time_pos =glo.Time_pos % glo.bn
    logWrite("置换完成，内存号：原数据：{}  ,新数据：{}" .format(block_id,data))
    # print("置换完成，内存号：原数据：{}  ,新数据：{}" .format(block_id,data))


'''
未来最近一次使用
for() //内存块内容和后面的数据匹配
'''
def block_use(block_content,p):
    for i in range(p+1,glo.dataNum):
        if glo.a[i] == block_content:
            return i
    return glo.dataNum

'''
void block_substitution_FIFO(int p)//FIFO页面置换,p号数据
'''
def block_substitution_FIFO(p):
    block_id = block_find_by_Time()#//找到替换的内存块，更新
    block_update(glo.a[p],block_id,True)

'''
void block_substitution_OPT(int p)//opt页面置换,p号数据
'''
def block_substitution_OPT(p):
    LastPosition = -1
    block_id = -1
    for i in range(m1.pos): #//遍历内存块
        position = block_use(m1.getblock(i),p)
        if position > LastPosition:
            LastPosition = position
            block_id = i
    #//找到替换的内存块，更新
    block_update(glo.a[p],block_id)
'''
'''
def block_find(x):
    for i in range(glo.bn):
        if m1.getblock(i) == x :
            return i
    return -1
'''
内存初始化
'''
def init_block():
    m1.init_M()#//基本初始化
    glo.Time_count = 0
    print("内存块总数：",end='')
    glo.bn = int(input())
    logWrite("内存块总数：{}".format(glo.bn))
    for i in range(glo.bn): # -1填充几个可以直接使用的内存块
        m1.block.append(-1)
    for i in range(glo.bn):#-1填充每个计数器
        glo.Time.append(-1)
    print('内存原存有数据 总数：')
    n = int(input())#//原有数据,必定都可以存入，n <= MAX
    logWrite('内存原存有数据 总数：{}'.format(n))
    if n:
        print("开启计数器？")
        print('1：开启')
        print("回车：关闭")
        print('============================')
        # //f:计数器开启标志,空回车为False
        f = bool(input())
        print("原数据分别为(多行输入)：")
        b = []
        while n:
            # x 数据
            x = int(input())
            b.append(x)
            block_insert(x,f)
            n = n -1
        logWrite("原数据分别为(多行输入)：{}".format(b))
'''
插入内容
'''
def block_insert(x,f = False):#//初始时存入,默认关闭计数器
    m1.block[m1.pos] = x
    m1.pos = m1.pos+1
    if f == True:
        glo.Time_count = glo.Time_count +1
        glo.Time[glo.Time_pos] =glo.Time_count
        glo.Time_pos = glo.Time_pos+1
        glo.Time_pos = glo.Time_pos % glo.bn

'''
OPT算法，默认开启日志log.txt
'''
def OPT():
    print('>>>>>>>>>>>>>>>>>正在进行 OPT 最佳置换算法测试<<<<<<<<<<<<<<<<<<')
    logWrite('>>>>>>>>>>>>>>>>>正在进行 OPT 最佳置换算法测试<<<<<<<<<<<<<<<<<<')
    print("测试数据总数：")
    n = int(input())
    glo.dataNum = n
    logWrite('测试数据总数：{}'.format(n))
    print("分别为(逐行输入)：")
    for i in range(n):
        x = int(input())
        glo.a.append(x)
    logWrite('分别为：{}'.format(glo.a))
    for i in range(n):
        res =block_find(glo.a[i])
        if res >=0:
            logWrite("{} 已存在，在第{} 个内存块中".format(glo.a[i], res))
        else:
            logWrite("{} 不在内存块中，将插入或置换".format(glo.a[i]))
            m1.upRMCount()#//缺页中断一次
            f = m1.isFull()
            if f == -100:
                logWrite("内存块已满，将执行置换")
                m1.upRCount()#//置换一次
                block_substitution_OPT(i)
            else:
                logWrite("内存未满，将{} 添加到空闲块中，内存块号：{}".format(glo.a[i], f))
                block_insert(glo.a[i])
    logWrite("内存块最终结果：")
    m1.getBlocks()
    logWrite("缺页中断：{}次 页面置换：{}次" .format(m1.getRMCount(),m1.getRCount()))
    # print("缺页中断：{}次 页面置换：{}次" .format(m1.getRMCount(),m1.getRCount()))


'''
FIFO算法
'''
def FIFO():
    print(">>>>>>>>>>>>>>>>>正在进行 FIFO 先进先出置换算法测试<<<<<<<<<<<<<<<<<<")
    logWrite(">>>>>>>>>>>>>>>>>正在进行 FIFO 先进先出置换算法测试<<<<<<<<<<<<<<<<<<")
    print("测试数据总数：",end='')
    n = int(input())
    logWrite("测试数据总数：{}".format(n))
    glo.dataNum = n
    print("分别为（逐行输入）：")
    for i in range(n):
        x = int(input())
        glo.a.append(x)
    logWrite("分别为： {}".format(glo.a))
    for i in range(n):
        res =block_find(glo.a[i])
        if res >=0:
            # print("已存在，在第{} 个内存块中".format(res))
            logWrite("已存在，在第{} 个内存块中".format(res))
        else:
            logWrite("{}不在内存块中，插入或置换".format(glo.a[i]))
            # print("{}不在内存块中，插入或置换".format(glo.a[i]))
            m1.upRMCount()#//缺页中断一次
            f = m1.isFull()
            if f == -100:
                logWrite("内存块已满，将执行置换")
                # print("内存块已满，将执行置换")
                m1.upRCount()#//置换一次
                block_substitution_FIFO(i)
            else:
                logWrite("内存未满，将{} 添加到空闲块中，内存块号：{}".format(glo.a[i],f))
                # print("内存未满，将{} 添加到空闲块中，内存块号：{}".format(glo.a[i],f))
                block_insert(glo.a[i],True)
    logWrite("内存块最终结果：")
    # print("内存块最终结果：")
    m1.getBlocks()
    logWrite("缺页中断：{}次 页面置换：{} 次".format(m1.getRMCount(),m1.getRCount()))
    # print("缺页中断：{}次 页面置换：{} 次".format(m1.getRMCount(),m1.getRCount()))
'''
菜单
'''
def menu():
    print("============================")
    print("|      指令                |")
    print("| 0:  OPT算法              |")
    print("| 1:  FIFO算法             |")
    print("============================")
    print("指令:")
    x = int(input())
    if x == 0:
        OPT()
    elif x == 1:
        FIFO()
    else:
        print("输入指令有误，请检查")


def logWrite(txt):
    with open('./log.txt', 'a') as fp:
        fp.write(txt+'\n')